package com.eian.boot.crypto.impl.asymmetric;

import com.eian.boot.crypto.constant.CryptoConstants;
import com.eian.boot.crypto.core.DecryptStrategy;
import com.eian.boot.crypto.enums.CryptoAlgorithm;
import com.eian.boot.crypto.exception.CryptoException;
import com.eian.boot.crypto.model.CryptoContext;
import com.eian.boot.crypto.model.OutputFormat;
import com.eian.boot.crypto.utils.Base64Utils;
import com.eian.boot.crypto.utils.HexUtils;
import com.eian.boot.crypto.utils.KeyUtils;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;

/**
 * SM2 解密策略（国密）
 * <p>
 * 使用私钥解密
 *
 * @author eian
 */
public class SM2DecryptStrategy implements DecryptStrategy {

    @Override
    public CryptoAlgorithm algorithm() {
        return CryptoAlgorithm.SM2;
    }

    @Override
    public String decrypt(String ciphertext, CryptoContext context) {
        if (StringUtils.isEmpty(ciphertext)) {
            return ciphertext;
        }
        byte[] cipherBytes = context.getOutputFormat() == OutputFormat.HEX
                ? HexUtils.fromHex(ciphertext)
                : Base64Utils.decode(ciphertext);
        byte[] decrypted = decrypt(cipherBytes, context);
        return new String(decrypted, StandardCharsets.UTF_8);
    }

    @Override
    public byte[] decrypt(byte[] ciphertext, CryptoContext context) {
        if (ciphertext == null || ciphertext.length == 0) {
            return ciphertext;
        }

        try {
            // 获取私钥
            if (StringUtils.isEmpty(context.getPrivateKey())) {
                throw new CryptoException("SM2 解密时必须提供私钥");
            }
            PrivateKey privateKey = KeyUtils.toPrivateKey(context.getPrivateKey(), CryptoConstants.Algorithm.SM2);

            // 执行解密（使用 BouncyCastle 提供者）
            Cipher cipher = Cipher.getInstance(algorithm().getTransformation(), CryptoConstants.Provider.BOUNCY_CASTLE);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(ciphertext);
        } catch (Exception e) {
            throw new CryptoException("SM2 解密失败", e);
        }
    }
}

